/*
* 最小生成树算法解析
* Prim 朴素 O(n^2) 邻接矩阵 枚举点 不可堆优化 

* Krusal O(mlogm) 存边 维护连通性使用并查集 已是最小生成树，加任意一条边就存在环，此时需要判决

* 
*/
#pragma GCC optimize("O1,O2,O3,Ofast")
#pragma GCC optimize("no-stack-protector,unroll-loops,fast-math,inline")
#pragma GCC target("avx,avx2,fma")
#pragma GCC target("sse,sse2,sse3,sse4,sse4.1,sse4.2,ssse3")

#include<iostream>
#include<cstring>
#include<algorithm>

// #define ONLINE_GUDGE
using LL = long long;
using namespace std;
const int N = 110, M = 10010, INF = 0x3f3f3f3f;

int n;
int path[N][N], dist[N]; // path存直连路径长 dist最短路径长 
bool st[N];

// void AddEdge(int a, int b, int c)
// { e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx++; }

// Prim
int prim()
{
    int res = 0;
    memset(dist, INF, sizeof dist);
    dist[1] = 0; // 起点

    for(int i = 1; i <= n; i++) // 执行n次
    {
        int now = -1;
        for(int j = 1; j <= n; j++)
            if(!st[j] && (now == -1 || dist[now] > dist[j])) // 点j没有访问 && (首轮 || now可以被更新)
                now = j; // 找集合外距离集合最近的点

        res += dist[now];
        st[now] = 1; // 加入集合

        for(int j = 1; j <= n; j++)
            dist[j] = min(dist[j], path[now][j]);

    }

    return res;
}

// Krusal
struct edge{    //用结构体存储每条边
    int f,t,w;
    bool operator<(const edge &W)const{
        return w<W.w;
    }
}edges[M];
int fa[N];
int from(int x){    //并查集找根节点
    if(fa[x]!=x)
        fa[x]=from(fa[x]);
    return fa[x];
}
int cnt, ans;

int main()
{
    #ifdef ONLINE_JUDGE

    #else
        freopen("./in.txt", "r", stdin);
    #endif

    ios::sync_with_stdio(0); cin.tie(0);

    cin >> n;

    /* Prim
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            cin >> path[i][j];
    
    cout << prim() << endl;
    */

    for(int i=1; i<=n; i++)
        for(int j=1; j<=n; j++){
            int w; cin >> w;
            edges[cnt++]=edge{i,j,w};  //加入当前的边
        }
    sort(edges, edges+cnt);  //对边进行排序

    for(int i=1; i<=n; i++)
        fa[i] = i;    //并查集初始化

    for(int i=0; i<cnt; i++){
        int f=from(edges[i].f),t=from(edges[i].t);
        if(f!=t){   //当前两点不连通
            ans+=edges[i].w;    //更新答案
            fa[f]=t;    //让两点变连通
        }
    }
    cout << ans << endl;
    return 0;
}